﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;

namespace Kangaroo.Controls
{
    public sealed class DiskSpaceMonitor : IDisposable
    {
        private const int CheckInterval = 5000;
        private readonly long _alertSpaceQuotaInBytes;
        private readonly char[] _volumes;
        private readonly Timer _timer;

        public DiskSpaceMonitor(long alertSpaceQuotaInBytes, params char[] volumes)
        {
            _alertSpaceQuotaInBytes = alertSpaceQuotaInBytes;
            _volumes = volumes;
            _timer = new Timer(OnTimerCallback, null, CheckInterval, CheckInterval);
        }

        private void OnTimerCallback(object state)
        {
            var volumesToAlert = _volumes
                .Where(v => IsDiskSpaceLowerThan(v, _alertSpaceQuotaInBytes))
                .ToArray();
            if(volumesToAlert.Any())
            {
                OnDiskSpaceAlert(volumesToAlert);
            }
            else
            {
                OnDiskSpaceGood();
            }
        }

        public void Dispose()
        {
            _timer.Change(-1, -1);
            _timer.Dispose();
        }

        public event EventHandler<EventArgs<char[]>> DiskSpaceAlert;

        private void OnDiskSpaceAlert(char[] volumes)
        {
            var handler = DiskSpaceAlert;
            if(handler != null)
                handler(this, new EventArgs<char[]>(volumes));
        }

        public event EventHandler<EventArgs> DiskSpaceGood;

        private void OnDiskSpaceGood()
        {
            var handler = DiskSpaceGood;
            if(handler != null)
                handler(this, EventArgs.Empty);
        }

        private static bool IsDiskSpaceLowerThan(char volume, long quotaInBytes)
        {
            try
            {
                var driveInfo = new DriveInfo(volume.ToString(CultureInfo.InvariantCulture));
                return driveInfo.AvailableFreeSpace < quotaInBytes;
            }
            catch (DriveNotFoundException)
            {
                // TODO: Log error.
                return true;
            }
        }
    }
}
